package viewModel;

import java.io.IOException;
import java.util.Stack;

import org.zkoss.bind.annotation.Command;
import org.zkoss.bind.annotation.GlobalCommand;
import org.zkoss.bind.annotation.Init;
import org.zkoss.bind.annotation.NotifyChange;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.Sessions;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zul.Messagebox;

import Controller.UserCredentialManager;
import ExamPDFCreation.PDFFileCreator;
import Misc.Variables;
import Misc.Exceptions.questionsPointSumAndTotalNotMatchingException;
import databaseHelper.CreateExamDAO;
import datatypes.Exam;
import datatypes.Exercise;
import datatypes.GradingKey;

/**
 * View Model for the Exam Creator.
 * 
 * used for loading data when chaging an exam
 * 
 * saves data if wanted to by the server
 * 
 * @author Rupert
 *
 */
public class CreateExamViewModel{
		
	/**
	 * Exam to be added
	 */
	private Exam newExam  = new Exam();
	
	/**
	 * GradingKey
	 */
	GradingKey gradingKey = new GradingKey();
	
	/**
	 * exam to be edited
	 */
	private int examId;
	
	/**
	 * change
	 */
	private boolean change = false;
	
	/**
	 * Stack for exercises from the Composer
	 */
	private Stack<Exercise> exercises = new Stack<Exercise>(); 
	
	/**
	 * Access to DB
	 */
	private CreateExamDAO createExamDAO = new CreateExamDAO();
	
	/**
	 * on initialization it is checked whether the exam should be created or edited.
	 * 
	 * This loads data from the dbs if necessary.
	 */
	@Init
	@NotifyChange({"gradingKey","newExam"})
    public void init(){
		
		System.out.println("CREATE EXAM INITIALIZATION!");
		
		// edit?
		Object tmpObject =Sessions.getCurrent().getAttribute(Variables.editExamSessionAttribut);
		if(tmpObject == null){
			System.out.println("Not Change");
			System.out.println("examId: "+examId);
			return;
		}
		

		Sessions.getCurrent().removeAttribute(Variables.editExamSessionAttribut);
		// get id of exam to change
		System.out.println("Change");
		int examId = new Integer(tmpObject.toString());
		this.examId = examId;
		
		change = true;
		// load data from db
		newExam = createExamDAO.getExamInformation(examId);
		
		gradingKey = createExamDAO.getGradingKey(examId);
		
		System.out.println("examId: "+examId);
    }

	/**
	 * Grading key proposal
	 */
	@Command("fillGradingKey")
	@NotifyChange("gradingKey")
	public void fillGradingKey(){
				
		try {
			exercises = CreateExamViewComposer.getExerciseStack();
		} catch (questionsPointSumAndTotalNotMatchingException e) {
			Messagebox.show("The sum of the single free text question is not matching with the total points!");
			return;
		}
		

		double maxPoints = getMaxPoints();
		
		double gradingStep =  0.06 * maxPoints;
		
		GradingKey newGradingKey = new GradingKey();
		
		newGradingKey.setgrade10(maxPoints - (int)Math.floor(gradingStep));
		newGradingKey.setgrade13(maxPoints - (int)Math.floor(2*gradingStep));
		newGradingKey.setgrade17(maxPoints - (int)Math.floor(3*gradingStep));
		newGradingKey.setgrade20(maxPoints - (int)Math.floor(4*gradingStep));
		newGradingKey.setgrade23(maxPoints - (int)Math.floor(5*gradingStep));
		newGradingKey.setgrade27(maxPoints - (int)Math.floor(6*gradingStep));
		newGradingKey.setgrade30(maxPoints - (int)Math.floor(7*gradingStep));
		newGradingKey.setgrade33(maxPoints - (int)Math.floor(8*gradingStep));
		newGradingKey.setgrade37(maxPoints - (int)Math.floor(9*gradingStep));
		newGradingKey.setgrade40(maxPoints - (int)Math.floor(10*gradingStep));
		newGradingKey.setgrade43(maxPoints - (int)Math.floor(11*gradingStep));
		newGradingKey.setgrade47(maxPoints - (int)Math.floor(12*gradingStep));
		
		this.gradingKey = newGradingKey;
	
	}
	
	/**
	 * save grading key
	 */
	@Command("saveGradingKey")
	public void saveGradingKey(){
		
		if(examId < 1){
			Messagebox.show("Saving a grading key is only possible on editing!");
			return;
		}
		
		double maxPoints = getMaxPoints();
		
		if(!gradingKey.checkCorrectnes(maxPoints)){
			Messagebox.show("Please insert the grading key meaningful: e.g. 1.0 requires more points than 1.3 ");
			return;
		}
		
		createExamDAO.changeGradingKey(examId, gradingKey);
		
	}
	
	
	private double getMaxPoints(){
		try {
			exercises = CreateExamViewComposer.getExerciseStack();
		} catch (questionsPointSumAndTotalNotMatchingException e) {
			Messagebox.show("The sum of the single free text question is not matching with the total points!");
			return 0;
		}
		
		double maxPoints = 0;
		for(Exercise exercise : exercises){
			maxPoints = maxPoints + exercise.getMaxPoints();
		}
		
		return maxPoints;
	}
	
	
	@Command("saveExams")
	public void saveExams(){
		Messagebox.show("Are you finshed creating this exam? Do you want to save it now?", "Create Exam", Messagebox.OK |  Messagebox.CANCEL, Messagebox.QUESTION, new org.zkoss.zk.ui.event.EventListener<Event>() {
		    public void onEvent(Event evt) throws InterruptedException {
		        if (evt.getName().equals("onOK")) {
		        	saveExam();
		        } else if (evt.getName().equals("onCancel")) {
		            Messagebox.show("Saving cancelled", "Warning", Messagebox.OK, Messagebox.EXCLAMATION);
		        } else if (evt.getName().equals("onIgnore")) {
		            Messagebox.show("Ignore Save", "Warning", Messagebox.OK, Messagebox.EXCLAMATION);
		        } else {
		        }
		    }
		});
	}
	
	
	
	
	private void saveExam(){
		
		try {
			exercises = CreateExamViewComposer.getExerciseStack();
		} catch (questionsPointSumAndTotalNotMatchingException e) {
			Messagebox.show("The sum of the single free text question is not matching with the total points!");
			return;
		}
		
		System.out.println("Save: Exercise-Stack : " + exercises.size());
		
		newExam.setNumberOfExercises(exercises.size());
		
		double[] maxPointsPerExercise = new double[newExam.getNumberOfExercises()];
		
		for(int i=0; i<newExam.getNumberOfExercises(); i++){
			maxPointsPerExercise[i] = exercises.get(i).getMaxPoints();
		}
		
		newExam.setMaxPointsPerExercise(maxPointsPerExercise);
		
		double[] gradingArray = new double[12];
		gradingArray[0] = gradingKey.getgrade10();
		gradingArray[1] = gradingKey.getgrade13();
		gradingArray[2] = gradingKey.getgrade17();
		gradingArray[3] = gradingKey.getgrade20();
		gradingArray[4] = gradingKey.getgrade23();
		gradingArray[5] = gradingKey.getgrade27();
		gradingArray[6] = gradingKey.getgrade30();
		gradingArray[7] = gradingKey.getgrade33();
		gradingArray[8] = gradingKey.getgrade37();
		gradingArray[9] = gradingKey.getgrade40();
		gradingArray[10] = gradingKey.getgrade43();
		gradingArray[11] = gradingKey.getgrade47();
		
		newExam.setGradingArray(gradingArray);
		
		newExam.setExercises(exercises);
		
		UserCredentialManager user = (UserCredentialManager) Sessions.getCurrent().getAttribute(UserCredentialManager.KEY_USER_Model);
		if(user!= null){
			if(change){
				createExamDAO.removeExam(examId);
			}
			createExamDAO.insert(newExam, user.getUserId());
		}else{
			Executions.sendRedirect("login.zul");
		}
		
		// create TexFiles
		try {
			PDFFileCreator.createPDFFile(newExam);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		
		
	}
	
	
	/*
	 * SETTERS & GETTERS
	 */
	
	
	public void setNewExam(Exam newExam){
		this.newExam = newExam;

	}
	public Exam getNewExam(){
		return newExam;
	}
	
	public void setGradingKey(GradingKey gradingKey){
		this.gradingKey = gradingKey;
	}
	
	public GradingKey getGradingKey(){
		return gradingKey;
	}

	/**
	 * @return the change
	 */
	public boolean isChange() {
		return change;
	}

	/**
	 * @param change the change to set
	 */
	public void setChange(boolean change) {
		this.change = change;
	}
	
}
